View Issue Details

IDProjectCategoryView StatusLast Update
0001371T99X171.00 SKB EagleSWpublic2021-12-24 09:20
Reporter(ALTech) Younkwang Jung Assigned To(SW) Kerwin Chen Due Date
PriorityhighSeveritys4-minorReproducibilityhave not tried
Status closedResolutionopen 
Summary0001371: [Smart3][BTF][VoC] Please check if there is a kernel patch related to this ramoops
DescriptionHi Kerwin

A lot of ramoops are being collected now.
Please check if there is a kernel patch related to this issue based on the PC value ( console-ramoops-0 or dmesg-ramoops-0 )

===================================================
PC is at expire_timers+0x60/0x188
PC is at rb_erase+0x1b0/0x3a8
PC is at __mutex_lock_slowpath+0x80/0x178
PC is at stmmac_poll+0x1a0/0x908
PC is at binder_inc_ref_for_node+0x328/0x330
PC is at input_handle_event+0x190/0x530
PC is at watchdog_check_hardlockup_other_cpu+0x114/0x138
PC is at rb_insert_color+0x10/0x1a0
PC is at _raw_spin_lock+0x24/0x60
PC is at test_clear_page_writeback+0x17c/0x288 ( <== INTEK found a kernel patch related to this issue , https://jira.skbroadband.com/browse/BTFAML-777 )
PC is at binder_thread_read+0x2d0/0x1740
PC is at sink_support_dolby_vision+0x24/0xb8
PC is at 0x80000000ef
==========================================================

Please check the attached files here.

Thank you
YK.Jung
TagsNo tags attached.
Attach Tags

Users monitoring this issue

User List (ALTech) JunGyu Kim , (ALTech) SY Yoon , (SW) Brent Choi , (SW) Jacky Chiang

Activities

(ALTech) Younkwang Jung

2021-10-18 19:09

developer  

_raw_spin_lock.zip (347,992 bytes)
binder_inc_ref_for_node.zip (2,207,840 bytes)
binder_thread_read.zip (713,177 bytes)
input_handle_event.zip (2,630,553 bytes)
PC.zip (2,973,123 bytes)
stmmac_poll.zip (540,835 bytes)
rb_erase.zip (5,791,452 bytes)
rb_insert_color.zip (496,948 bytes)

(ALTech) Younkwang Jung

2021-10-18 19:16

developer  

expire_timers.zip (15,093,264 bytes)

(SW) Kerwin Chen

2021-10-19 15:52

developer   ~0008494

Hi YK,

Here is the patch for 'test_clear_page_writeback'.
Please let us know when to apply it.
Thanks !
d4a742865c.patch (9,868 bytes)   
From d4a742865c6b69ef931694745ef54965d7c9966c Mon Sep 17 00:00:00 2001
From: Johannes Weiner <hannes@cmpxchg.org>
Date: Fri, 18 Aug 2017 15:15:48 -0700
Subject: [PATCH] mm: memcontrol: fix NULL pointer crash in
 test_clear_page_writeback()

Jaegeuk and Brad report a NULL pointer crash when writeback ending tries
to update the memcg stats:

    BUG: unable to handle kernel NULL pointer dereference at 00000000000003b0
    IP: test_clear_page_writeback+0x12e/0x2c0
    [...]
    RIP: 0010:test_clear_page_writeback+0x12e/0x2c0
    Call Trace:
     <IRQ>
     end_page_writeback+0x47/0x70
     f2fs_write_end_io+0x76/0x180 [f2fs]
     bio_endio+0x9f/0x120
     blk_update_request+0xa8/0x2f0
     scsi_end_request+0x39/0x1d0
     scsi_io_completion+0x211/0x690
     scsi_finish_command+0xd9/0x120
     scsi_softirq_done+0x127/0x150
     __blk_mq_complete_request_remote+0x13/0x20
     flush_smp_call_function_queue+0x56/0x110
     generic_smp_call_function_single_interrupt+0x13/0x30
     smp_call_function_single_interrupt+0x27/0x40
     call_function_single_interrupt+0x89/0x90
    RIP: 0010:native_safe_halt+0x6/0x10

    (gdb) l *(test_clear_page_writeback+0x12e)
    0xffffffff811bae3e is in test_clear_page_writeback (./include/linux/memcontrol.h:619).
    614		mod_node_page_state(page_pgdat(page), idx, val);
    615		if (mem_cgroup_disabled() || !page->mem_cgroup)
    616			return;
    617		mod_memcg_state(page->mem_cgroup, idx, val);
    618		pn = page->mem_cgroup->nodeinfo[page_to_nid(page)];
    619		this_cpu_add(pn->lruvec_stat->count[idx], val);
    620	}
    621
    622	unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order,
    623							gfp_t gfp_mask,

The issue is that writeback doesn't hold a page reference and the page
might get freed after PG_writeback is cleared (and the mapping is
unlocked) in test_clear_page_writeback().  The stat functions looking up
the page's node or zone are safe, as those attributes are static across
allocation and free cycles.  But page->mem_cgroup is not, and it will
get cleared if we race with truncation or migration.

It appears this race window has been around for a while, but less likely
to trigger when the memcg stats were updated first thing after
PG_writeback is cleared.  Recent changes reshuffled this code to update
the global node stats before the memcg ones, though, stretching the race
window out to an extent where people can reproduce the problem.

Update test_clear_page_writeback() to look up and pin page->mem_cgroup
before clearing PG_writeback, then not use that pointer afterward.  It
is a partial revert of 62cccb8c8e7a ("mm: simplify lock_page_memcg()")
but leaves the pageref-holding callsites that aren't affected alone.

Change-Id: I87ea4c22492e8e3ccd9bceb36fba014fac04819e
Link: http://lkml.kernel.org/r/20170809183825.GA26387@cmpxchg.org
Fixes: 62cccb8c8e7a ("mm: simplify lock_page_memcg()")
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Reported-by: Jaegeuk Kim <jaegeuk@kernel.org>
Tested-by: Jaegeuk Kim <jaegeuk@kernel.org>
Reported-by: Bradley Bolen <bradleybolen@gmail.com>
Tested-by: Brad Bolen <bradleybolen@gmail.com>
Cc: Vladimir Davydov <vdavydov@virtuozzo.com>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: <stable@vger.kernel.org>	[4.6+]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Git-commit: 739f79fc9db1b38f96b5a5109b247a650fbebf6d
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
[guptap@codeaurora.org: Resolved merge conflicts]
Signed-off-by: Prakash Gupta <guptap@codeaurora.org>
---
 include/linux/memcontrol.h | 33 ++++++++++++++++++++++++-----
 mm/memcontrol.c            | 43 +++++++++++++++++++++++++++-----------
 mm/page-writeback.c        | 14 ++++++++++---
 3 files changed, 70 insertions(+), 20 deletions(-)

diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 8b35bdbdc214..fd77f8303ab9 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -490,9 +490,21 @@ bool mem_cgroup_oom_synchronize(bool wait);
 extern int do_swap_account;
 #endif
 
-void lock_page_memcg(struct page *page);
+struct mem_cgroup *lock_page_memcg(struct page *page);
+void __unlock_page_memcg(struct mem_cgroup *memcg);
 void unlock_page_memcg(struct page *page);
 
+static inline void __mem_cgroup_update_page_stat(struct page *page,
+						 struct mem_cgroup *memcg,
+						 enum mem_cgroup_stat_index idx,
+						 int val)
+{
+	VM_BUG_ON(!(rcu_read_lock_held() || PageLocked(page)));
+
+	if (memcg && memcg->stat)
+		this_cpu_add(memcg->stat->count[idx], val);
+}
+
 /**
  * mem_cgroup_update_page_stat - update page state statistics
  * @page: the page
@@ -508,13 +520,12 @@ void unlock_page_memcg(struct page *page);
  *     mem_cgroup_update_page_stat(page, state, -1);
  *   unlock_page(page) or unlock_page_memcg(page)
  */
+
 static inline void mem_cgroup_update_page_stat(struct page *page,
 				 enum mem_cgroup_stat_index idx, int val)
 {
-	VM_BUG_ON(!(rcu_read_lock_held() || PageLocked(page)));
 
-	if (page->mem_cgroup)
-		this_cpu_add(page->mem_cgroup->stat->count[idx], val);
+	__mem_cgroup_update_page_stat(page, page->mem_cgroup, idx, val);
 }
 
 static inline void mem_cgroup_inc_page_stat(struct page *page,
@@ -709,7 +720,12 @@ mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p)
 {
 }
 
-static inline void lock_page_memcg(struct page *page)
+static inline struct mem_cgroup *lock_page_memcg(struct page *page)
+{
+	return NULL;
+}
+
+static inline void __unlock_page_memcg(struct mem_cgroup *memcg)
 {
 }
 
@@ -745,6 +761,13 @@ static inline void mem_cgroup_update_page_stat(struct page *page,
 {
 }
 
+static inline void __mem_cgroup_update_page_stat(struct page *page,
+						 struct mem_cgroup *memcg,
+						 enum mem_cgroup_stat_index idx,
+						 int nr)
+{
+}
+
 static inline void mem_cgroup_inc_page_stat(struct page *page,
 					    enum mem_cgroup_stat_index idx)
 {
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index fce6c4827e49..37d63b27aa67 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1619,9 +1619,13 @@ cleanup:
  * @page: the page
  *
  * This function protects unlocked LRU pages from being moved to
- * another cgroup and stabilizes their page->mem_cgroup binding.
+ * another cgroup.
+ *
+ * It ensures lifetime of the returned memcg. Caller is responsible
+ * for the lifetime of the page; __unlock_page_memcg() is available
+ * when @page might get freed inside the locked section.
  */
-void lock_page_memcg(struct page *page)
+struct mem_cgroup *lock_page_memcg(struct page *page)
 {
 	struct mem_cgroup *memcg;
 	unsigned long flags;
@@ -1630,18 +1634,24 @@ void lock_page_memcg(struct page *page)
 	 * The RCU lock is held throughout the transaction.  The fast
 	 * path can get away without acquiring the memcg->move_lock
 	 * because page moving starts with an RCU grace period.
-	 */
+	 *
+	 * The RCU lock also protects the memcg from being freed when
+	 * the page state that is going to change is the only thing
+	 * preventing the page itself from being freed. E.g. writeback
+	 * doesn't hold a page reference and relies on PG_writeback to
+	 * keep off truncation, migration and so forth.
+         */
 	rcu_read_lock();
 
 	if (mem_cgroup_disabled())
-		return;
+		return NULL;
 again:
 	memcg = page->mem_cgroup;
 	if (unlikely(!memcg))
-		return;
+		return NULL;
 
 	if (atomic_read(&memcg->moving_account) <= 0)
-		return;
+		return memcg;
 
 	spin_lock_irqsave(&memcg->move_lock, flags);
 	if (memcg != page->mem_cgroup) {
@@ -1657,18 +1667,18 @@ again:
 	memcg->move_lock_task = current;
 	memcg->move_lock_flags = flags;
 
-	return;
+	return memcg;
 }
 EXPORT_SYMBOL(lock_page_memcg);
 
 /**
- * unlock_page_memcg - unlock a page->mem_cgroup binding
- * @page: the page
+ * __unlock_page_memcg - unlock and unpin a memcg
+ * @memcg: the memcg
+ *
+ * Unlock and unpin a memcg returned by lock_page_memcg().
  */
-void unlock_page_memcg(struct page *page)
+void __unlock_page_memcg(struct mem_cgroup *memcg)
 {
-	struct mem_cgroup *memcg = page->mem_cgroup;
-
 	if (memcg && memcg->move_lock_task == current) {
 		unsigned long flags = memcg->move_lock_flags;
 
@@ -1680,6 +1690,15 @@ void unlock_page_memcg(struct page *page)
 
 	rcu_read_unlock();
 }
+
+/**
+ * unlock_page_memcg - unlock a page->mem_cgroup binding
+ * @page: the page
+ */
+void unlock_page_memcg(struct page *page)
+{
+	__unlock_page_memcg(page->mem_cgroup);
+}
 EXPORT_SYMBOL(unlock_page_memcg);
 
 /*
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 439cc63ad903..dd7817cd3e07 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -2713,9 +2713,10 @@ EXPORT_SYMBOL(clear_page_dirty_for_io);
 int test_clear_page_writeback(struct page *page)
 {
 	struct address_space *mapping = page_mapping(page);
+	struct mem_cgroup *memcg;
 	int ret;
 
-	lock_page_memcg(page);
+	memcg = lock_page_memcg(page);
 	if (mapping && mapping_use_writeback_tags(mapping)) {
 		struct inode *inode = mapping->host;
 		struct backing_dev_info *bdi = inode_to_bdi(inode);
@@ -2743,13 +2744,20 @@ int test_clear_page_writeback(struct page *page)
 	} else {
 		ret = TestClearPageWriteback(page);
 	}
+	/*
+	 * NOTE: Page might be free now! Writeback doesn't hold a page
+	 * reference on its own, it relies on truncation to wait for
+	 * the clearing of PG_writeback. The below can only access
+	 * page state that is static across allocation cycles.
+	 */
 	if (ret) {
-		mem_cgroup_dec_page_stat(page, MEM_CGROUP_STAT_WRITEBACK);
+		__mem_cgroup_update_page_stat(page, memcg,
+					      MEM_CGROUP_STAT_WRITEBACK, -1);
 		dec_node_page_state(page, NR_WRITEBACK);
 		dec_zone_page_state(page, NR_ZONE_WRITE_PENDING);
 		inc_node_page_state(page, NR_WRITTEN);
 	}
-	unlock_page_memcg(page);
+	__unlock_page_memcg(memcg);
 	return ret;
 }
 
d4a742865c.patch (9,868 bytes)   

(ALTech) Younkwang Jung

2021-10-19 17:40

developer   ~0008497

Last edited: 2021-10-19 17:42

View 2 revisions

Hi kerwin

How can we check that this patch(test_clear_page_writeback) is no problem?
Also, please find other ramoops related patches.

Thanks
YK.Jung

(SW) Kerwin Chen

2021-10-20 08:34

developer   ~0008502

Hi YK,

I have no idea how to verify patch for 'test_clear_page_writeback'.
It is a formal patch of kernel mainline and is found easily by Google search.
Currently, I don't find patch for other ramoop dumps.

BTW, it is hard to find root cause just based dump of ramoops.
Reproduce steps are also important to fix it.
Thanks !

(ALTech) Younkwang Jung

2021-10-25 08:32

developer   ~0008572

Hi Kerwin

If it's an formal patch , please apply it to UI532.
And we will apply it to the next test FW and proceed with the test.

Thanks
YK.Jung

(SW) Kerwin Chen

2021-10-25 09:30

developer   ~0008574

Hi YK,

Please check link below for official commit of 'test_clear_page_writeback'.
https://android.googlesource.com/kernel/common/+/dee92931fb17fbdb05d3521512cf76b59c2b2648

Thanks!

(ALTech) Younkwang Jung

2021-10-29 07:30

developer   ~0008623

Hi Kerwin

In the case of INTEK, they are doing the test as follows.
https://jira.skbroadband.com/browse/BTFAML-777

========================================================================================
When INTEK scanned Google SPL details related to the issue, INTEK found a patch related to test_clear_page_writeback as below.
https://android.googlesource.com/kernel/common/+/75e3d3ba7f7f4a032df1d7ff271229703b362991

However, unlike the current SMART3 kernel version, the entire patch cannot be applied and only the test_clear_page_writeback-related part is applied, and the stability test is being conducted.

commit id : efb6c387363
=========================================================================================================

Please check this patch mentioned by INTEK.
Thank you
YK.Jung

(SW) Kerwin Chen

2021-10-29 09:19

developer   ~0008626

Hi YK,

Intek's patch is to migrate kernel from 4.9.180 to 4.9.257.
I can't tell which commit fix 'test_clear_page_writeback' issue.
Please ask Intek to share link of Google SPL.

Thanks !

(ALTech) Younkwang Jung

2021-11-01 13:00

developer   ~0008635

Hi Kerwin

There is an additional analysis of AMLOGIC for rb_erase RAMOOPS.
https://jira.skbroadband.com/browse/BTFAML-807

< count >
[skb_voc_manager.py: 682 - __MakeOdmReport() ] pc PC is at rb_erase+0x1b0/0x3a8 count 50
[skb_voc_manager.py: 682 - __MakeOdmReport() ] pc PC is at rb_erase+0x198/0x3a8 count 42
[skb_voc_manager.py: 682 - __MakeOdmReport() ] pc PC is at rb_erase+0x120/0x3a8 count 17
[skb_voc_manager.py: 682 - __MakeOdmReport() ] pc PC is at rb_erase+0x108/0x3a8 count 4

===============================================================================================================================================
PC is at rb_erase+0x1b0/0x3a8
Line 117 of "/mnt/fileroot/james.park/BFX-AT100_5.3.1_PURE/common/include/linux/rbtree_augmented.h" starts at address 0xffffff80094a39e8 <rb_erase+432> and ends at 0xffffff80094a39ec <rb_erase+436>.
(gdb) list rbtree_augmented.h:117
112 }
113
114 static inline void rb_set_parent_color(struct rb_node *rb,
115 struct rb_node *p, int color)
116 {
117 rb->__rb_parent_color = (unsigned long)p | color;
118 }
119
120 static inline void
121 __rb_change_child(struct rb_node *old, struct rb_node *new,

PC is at rb_erase+0x198/0x3a8
(gdb) info line *0xffffff80094a39d0
Line 340 of "/mnt/fileroot/james.park/BFX-AT100_5.3.1_PURE/common/lib/rbtree.c" starts at address 0xffffff80094a39d0 <rb_erase+408> and ends at 0xffffff80094a39d8 <rb_erase+416>.
(gdb) list rbtree.c:340
335 RB_BLACK);
336 augment_rotate(parent, sibling);
337 break;
338 } else {
339 sibling = parent->rb_left;
340 if (rb_is_red(sibling)) { <- sibling is NULL here
341 /* Case 1 - right rotate at parent */
342 tmp1 = sibling->rb_right;
343 WRITE_ONCE(parent->rb_left, tmp1);
344 WRITE_ONCE(sibling->rb_right, parent);
 
rb_erase+0x120/0x3a8
(gdb) info line *0xffffff80094a3958
Line 117 of "/mnt/fileroot/james.park/BFX-AT100_5.3.1_PURE/common/include/linux/rbtree_augmented.h" starts at address 0xffffff80094a3958 <rb_erase+288> and ends at 0xffffff80094a395c <rb_erase+292>.
(gdb) list rbtree_augmented.h:117
112 }
113
114 static inline void rb_set_parent_color(struct rb_node *rb,
115 struct rb_node *p, int color)
116 {
117 rb->__rb_parent_color = (unsigned long)p | color; <- rb is NULL here
118 }
 
PC is at rb_erase+0x108/0x3a8
(gdb) info line *0xffffff80094a3940
Line 243 of "/mnt/fileroot/james.park/BFX-AT100_5.3.1_PURE/common/lib/rbtree.c" starts at address 0xffffff80094a3940 <rb_erase+264> and ends at 0xffffff80094a3948 <rb_erase+272>.
(gdb) list rbtree.c:243
238 * - All leaf paths going through parent and node have a
239 * black node count that is 1 lower than other leaf paths.
240 */
241 sibling = parent->rb_right;
242 if (node != sibling) { /* node == parent->rb_left */
243 if (rb_is_red(sibling)) { <- sibling is NULL here
244 /*
245 * Case 1 - left rotate at parent
246 *
247 * P S

=======================================================================================================================================
That is, the current issue occurs when rb_right or rb_left in the parent node is NULL in the function __rb_erase_color().
There seems to be a specific reason because the pattern is the same, but we couldn't figure out whether it would be there because it couldn't be reproduced.

Please check the related kernel patch or related content.
Thank you
YK.Jung

(SW) Kerwin Chen

2021-11-03 11:02

developer   ~0008654

Hi YK,

I don't find correct patch for 'rb_earse()' issue.
Smart3 use kernel 4.9 for Android 10, there is no update in rbtree.c.
Even I see there are some commits for 'rbtree.c' on kernel 5.15, I can't tell if it is OK to apply.

Thanks !

Issue History

Date Modified Username Field Change
2021-10-18 19:09 (ALTech) Younkwang Jung New Issue
2021-10-18 19:09 (ALTech) Younkwang Jung Status new => assigned
2021-10-18 19:09 (ALTech) Younkwang Jung Assigned To => (SW) Kerwin Chen
2021-10-18 19:09 (ALTech) Younkwang Jung File Added: _raw_spin_lock.zip
2021-10-18 19:09 (ALTech) Younkwang Jung File Added: binder_inc_ref_for_node.zip
2021-10-18 19:09 (ALTech) Younkwang Jung File Added: binder_thread_read.zip
2021-10-18 19:09 (ALTech) Younkwang Jung File Added: input_handle_event.zip
2021-10-18 19:09 (ALTech) Younkwang Jung File Added: PC.zip
2021-10-18 19:09 (ALTech) Younkwang Jung File Added: sink_support_dolby_vision.zip
2021-10-18 19:09 (ALTech) Younkwang Jung File Added: stmmac_poll.zip
2021-10-18 19:09 (ALTech) Younkwang Jung File Added: test_clear_page_writeback.zip
2021-10-18 19:09 (ALTech) Younkwang Jung File Added: watchdog_check_hardlockup_other_cpu.zip
2021-10-18 19:09 (ALTech) Younkwang Jung File Added: rb_erase.zip
2021-10-18 19:09 (ALTech) Younkwang Jung File Added: rb_insert_color.zip
2021-10-18 19:16 (ALTech) Younkwang Jung File Added: expire_timers.zip
2021-10-18 19:17 (ALTech) Younkwang Jung Description Updated View Revisions
2021-10-18 19:17 (ALTech) Younkwang Jung Issue Monitored: (SW) Brent Choi
2021-10-18 19:17 (ALTech) Younkwang Jung Issue Monitored: (ALTech) SY Yoon
2021-10-18 19:17 (ALTech) Younkwang Jung Issue Monitored: (ALTech) JunGyu Kim
2021-10-19 15:52 (SW) Kerwin Chen File Added: d4a742865c.patch
2021-10-19 15:52 (SW) Kerwin Chen Note Added: 0008494
2021-10-19 17:40 (ALTech) Younkwang Jung Note Added: 0008497
2021-10-19 17:42 (ALTech) Younkwang Jung Note Edited: 0008497 View Revisions
2021-10-20 08:34 (SW) Kerwin Chen Note Added: 0008502
2021-10-20 14:20 (SW) Jacky Chiang Issue Monitored: (SW) Jacky Chiang
2021-10-25 08:32 (ALTech) Younkwang Jung Note Added: 0008572
2021-10-25 09:30 (SW) Kerwin Chen Note Added: 0008574
2021-10-29 07:30 (ALTech) Younkwang Jung Note Added: 0008623
2021-10-29 09:19 (SW) Kerwin Chen Note Added: 0008626
2021-11-01 13:00 (ALTech) Younkwang Jung Note Added: 0008635
2021-11-03 11:02 (SW) Kerwin Chen Note Added: 0008654
2021-12-23 16:34 (SW) Kerwin Chen Severity s2-severe => s3-moderate
2021-12-24 09:20 (SW) Kerwin Chen Severity s3-moderate => s4-minor
2021-12-24 09:20 (SW) Kerwin Chen Status assigned => closed